package com.itany.shop.util;

import com.itany.shop.exception.DataAccessException;
import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
 * @Author:石小俊
 * @Date:2022/12/15 10:05
 * @Version:1.0-SNAPSHOT
 * @Description: JDBC工具类
 * 使用这个类加载类加载路径根目录下的dataSource.properties文件中的配置
 * 创建一个线程单例的连接
 * 此处使用commons-dbcp实现
 */
public class JDBCUtil {

    private static DataSource ds;
    private static ThreadLocal<Connection> local;

    static{
        local = new ThreadLocal<>();
        Properties properties = new Properties();
        try {
            properties.load(JDBCUtil.class.getClassLoader().getResourceAsStream("dataSource.properties"));
            ds = BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ExceptionInInitializerError("JDBCUtil初始化失败");
        }
    }

    /**
     * 获取连接
     * 使用连接池获取一个连接,该连接要求线程单例
     * @return
     */
    public static Connection getConnection(){
        // 从线程池中取出连接
        Connection conn = local.get();

        try {
            // 如果线程池中没有连接
            if(null == conn){
                // 需要获取一个新的连接
                conn = ds.getConnection();
                // 并放入到线程池中
                local.set(conn);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new DataAccessException("获取连接失败");
        }

        // 如果存在连接,直接返回
        return conn;
    }

    /**
     * 释放持久层资源
     * @param conn
     * @param ps
     * @param rs
     */
    public static void  close(Connection conn, PreparedStatement ps, ResultSet rs){
        try {
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new DataAccessException("释放连接出错");
        }
        try {
            if(ps != null){
                ps.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new DataAccessException("释放状态集出错");
        }
        try {
            if(rs != null){
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new DataAccessException("释放结果集出错");
        }
    }

    /**
     * 释放业务层资源
     */
    public static void close(){
        // 取出线程池中的连接
        Connection conn = local.get();
        // 如果当前连接尚未释放
        if(conn != null){
            try {
                // 释放资源
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
                throw new DataAccessException("释放连接出错");
            }
            // 将连接从线程池中移除
            local.remove();
        }
    }
}
